home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byt87ibm.arc / RDUNCAN.ARC / STAMPER.ASM next >
Assembly Source File  |  1987-09-27  |  16KB  |  432 lines

  1. ----------------------------------------------------------------------
  2. The MASM source file:  STAMPER.ASM
  3. ----------------------------------------------------------------------
  4.  
  5.         name    stamper
  6.         page    55,132
  7.         title   STAMPER: a simple keyboard monitor
  8.         .286c   
  9.         .sall
  10. ; STAMPER.EXE: a simple OS/2 monitor that inserts
  11. ; a date or time stamp into the keyboard data stream.
  12. ;
  13. ; Alt-D  is the hot-key for a date-stamp.
  14. ; Alt-T  is the hot-key for a time-stamp.
  15. ; Alt-X  causes the STAMPER.EXE monitor to exit.
  16. ;
  17. ; Copyright (C) 1987 Ray Duncan
  18. ;
  19. ; To assemble and link this program:
  20. ;
  21. ;       MASM stamper;
  22. ;       LINK stamper,,,DOSCALLS,stamper;
  23. ;
  24. ; To use this program, execute it with the command:
  25. ;
  26. ;       C>DETACH STAMPER
  27. ;
  28.  
  29. stdin   equ     0                       ; standard device handles
  30. stdout  equ     1
  31. stderr  equ     2
  32.  
  33. cr      equ     0dh                     ; ASCII carriage return
  34. lf      equ     0ah                     ; ASCII line feed
  35.  
  36.                                         ; Hot-key definitions:
  37. datekey equ     20h                     ; Alt-D
  38. timekey equ     14h                     ; Alt-T
  39. exitkey equ     2dh                     ; Alt-X
  40.  
  41.         extrn   DOSGETINFOSEG:far       ; OS/2 API services needed
  42.         extrn   DOSEXIT:far             
  43.         extrn   DOSSLEEP:far
  44.         extrn   DOSWRITE:far
  45.         extrn   DOSMONOPEN:far          
  46.         extrn   DOSMONCLOSE:far
  47.         extrn   DOSMONREG:far
  48.         extrn   DOSMONREAD:far
  49.         extrn   DOSMONWRITE:far
  50.         extrn   VIOPOPUP:far
  51.         extrn   VIOENDPOPUP:far
  52.         extrn   VIOWRTCHARSTR:far
  53.  
  54. jerr    macro   target                  ; Macro to test return code
  55.         local   zero                    ; in AX and jump if non-zero.
  56.         or      ax,ax                   ; Uses JMP DISP16 to avoid
  57.         jz      zero                    ; branch out of range errors
  58.         jmp     target
  59. zero:
  60.         endm
  61.  
  62.  
  63. DGROUP  group   _DATA
  64.  
  65. _DATA   segment word public 'DATA'
  66.  
  67. popflag dw      1                       ; wait for PopUp window
  68. wlen    dw      ?                       ; receives length written
  69.  
  70. kname   db      '\DEV\KBD$',0           ; device name of keyboard
  71. khandle dw      0                       ; handle from DosMonOpen
  72.  
  73. gseg    dw      ?                       ; global information segment
  74. lseg    dw      ?                       ; local information segment
  75.  
  76. scrgrp  dw      ?                       ; foreground screen group 
  77.  
  78. dstr    db      'mm/dd/yy',0            ; strings used by time and
  79. tstr    db      'hh:mm',0               ; date formatting routines
  80.  
  81. monin   dw      128,64 dup (0)          ; buffers for monitor
  82. monout  dw      128,64 dup (0)
  83.  
  84. packet  db      128 dup (0)             ; buffer for kbd data packet
  85. pktlen  dw      ?                       ; length of buffer prior to read
  86.                                         ; call, length of data after.
  87.  
  88. msg1    db      cr,lf,'Start STAMPER with DETACH!',cr,lf
  89. msg1_len equ $-msg1             
  90.  
  91. msg2    db      'STAMPER utility installed!'
  92. msg2_len equ $-msg2
  93.  
  94. msg3    db      'Alt-D to insert date stamp.'
  95. msg3_len equ $-msg3
  96.  
  97. msg4    db      'Alt-T to insert time stamp.'
  98. msg4_len equ $-msg4
  99.  
  100. msg5    db      'Alt-X to shut down STAMPER.'
  101. msg5_len equ $-msg5
  102.  
  103. msg6    db      'STAMPER utility deactivated.'
  104. msg6_len equ $-msg6
  105.  
  106. msg7    db      cr,lf,'Unexpected OS/2 error',cr,lf
  107. msg7_len equ $-msg7
  108.  
  109. _DATA   ends
  110.  
  111.  
  112. _TEXT   segment word public 'CODE'
  113.  
  114.         assume  cs:_TEXT,ds:DGROUP,ss:DGROUP
  115.  
  116.  
  117. main    proc    far                     ; entry point from OS/2
  118.  
  119.         push    ds                      ; get selectors for system's
  120.         push    offset DGROUP:gseg      ; global information segments
  121.         push    ds
  122.         push    offset DGROUP:lseg
  123.         call    DOSGETINFOSEG           ; transfer to OS/2
  124.         jerr    error                   ; give up if can't get selectors
  125.  
  126.         mov     es,lseg                 ; get our screen group number
  127.         mov     ax,es:[8]               ; and make sure we are detached
  128.         cmp     ax,16
  129.         je      main1                   ; proceed, all is well
  130.  
  131.                                         ; not run with DETACH, 
  132.                                         ; display error message...
  133.         push    stderr                  ; handle for standard error
  134.         push    ds                      ; address of message
  135.         push    offset DGROUP:msg1
  136.         push    msg1_len                ; length of message
  137.         jmp     error2                  ; go display and exit
  138.  
  139. main1:  mov     es,gseg                 ; get foreground screen group 
  140.         mov     al,byte ptr es:[0018h]  ; from global info segment
  141.         cbw
  142.         mov     scrgrp,ax
  143.  
  144.                                         ; open monitor connection... 
  145.         push    ds                      ; address of name \DEV\KBD$ 
  146.         push    offset DGROUP:kname
  147.         push    ds                      ; address to receive monitor handle
  148.         push    offset DGROUP:khandle
  149.         call    DOSMONOPEN              ; transfer to OS/2
  150.         jerr    error                   ; give up if can't open it
  151.  
  152.                                         ; register as keyboard monitor...
  153.         push    khandle                 ; handle from DosMonOpen
  154.         push    ds                      ; addr of monitor input buffer
  155.         push    offset DGROUP:monin
  156.         push    ds                      ; addr of monitor output buffer
  157.         push    offset DGROUP:monout
  158.         push    1                       ; request front of list
  159.         push    scrgrp                  ; screen group we are monitoring
  160.         call    DOSMONREG               ; transfer to OS/2
  161.         jerr    error                   ; give up if can't register
  162.  
  163.         call    signon                  ; else announce our presence 
  164.  
  165. main2:                                  ; monitor the keyboard character
  166.                                         ; stream; when hot key detected,
  167.                                         ; insert the appropriate date or
  168.                                         ; time stamp, or exit.
  169.  
  170.         mov     pktlen,pktlen-packet    ; set max buffer length for read
  171.  
  172.                                         ; get next keyboard data packet
  173.         push    ds                      ; address of monitor input buffer
  174.         push    offset DGROUP:monin
  175.         push    0                       ; wait until data available
  176.         push    ds
  177.         push    offset DGROUP:packet    ; buffer for keyboard data packet
  178.         push    ds
  179.         push    offset DGROUP:pktlen    ; receives length of data packet
  180.         call    DOSMONREAD              ; transfer to OS/2
  181.  
  182.         cmp     byte ptr packet+2,0     ; is this extended code?
  183.         jnz     main4                   ; no, just pass it on
  184.  
  185.         cmp     byte ptr packet+3,exitkey
  186.         jz      main5                   ; jump if exit hot-key
  187.  
  188.         cmp     byte ptr packet+3,timekey
  189.         jnz     main3                   ; jump if not time hot-key
  190.  
  191.         cmp     word ptr packet+12,0    ; discard break packets
  192.         jnz     main2
  193.  
  194.         call    time                    ; insert the time stamp
  195.  
  196.         jmp     main2                   ; discard this key
  197.  
  198. main3:                                  ; is it datestamp hot-key?
  199.         cmp     byte ptr packet+3,datekey
  200.         jnz     main4                   ; no, jump
  201.  
  202.         cmp     word ptr packet+12,0    ; discard break packets
  203.         jnz     main2
  204.  
  205.         call    date                    ; insert the date stamp
  206.  
  207.         jmp     main2                   ; discard this key
  208.  
  209. main4:                                  ; Not hot-key, pass packet on.
  210.         push    ds                      ; address of monitor output buffer
  211.         push    offset DGROUP:monout
  212.         push    ds                      ; address of keyboard data packet
  213.         push    offset DGROUP:packet    
  214.         push    pktlen                  ; length of data packet
  215.         call    DOSMONWRITE             ; transfer to OS/2      
  216.         
  217.         jmp     main2                   ; wait for another packet
  218.  
  219. main5:                                  ; hotkey for de-install detected
  220.  
  221.         cmp     word ptr packet+12,0    ; make sure it's Break packet
  222.         jz      main2                   ; if not just discard it
  223.  
  224.         push    khandle                 ; close the monitor connection
  225.         call    DOSMONCLOSE
  226.         jerr    error
  227.  
  228.         call    signoff                 ; announce STAMPER exit 
  229.  
  230.         push    1                       ; terminate all threads
  231.         push    0                       ; return success code
  232.         call    DOSEXIT                 ; final exit to OS/2
  233.  
  234. main    endp
  235.  
  236.  
  237. error   proc    near                    ; unilateral termination 
  238.                                         ; because of unexpected error.
  239.  
  240.         cmp     khandle,0               ; first shut down monitor
  241.         je      error1                  ; if it is active
  242.         push    khandle
  243.         call    DOSMONCLOSE             ; ignore any error codes
  244.  
  245. error1:                                 ; write message 'Unexpected error'
  246.         push    stderr                  ; handle for standard error device
  247.         push    ds                      ; address of message
  248.         push    offset DGROUP:msg7
  249.         push    msg7_len                ; length of message
  250.  
  251. error2: push    ds                      ; receives bytes written
  252.         push    offset DGROUP:wlen
  253.         call    DOSWRITE                ; transfer to OS/2
  254.  
  255.         push    1                       ; terminate all threads
  256.         push    1                       ; return error code
  257.         call    DOSEXIT                 ; final exit to OS/2
  258.  
  259. error   endp
  260.  
  261.  
  262. date    proc    near                    ; format and insert date stamp
  263.  
  264.         mov     es,gseg                 ; get selector for global
  265.                                         ; read-only information segment 
  266.  
  267.         mov     al,byte ptr es:[11h]    ; convert month to ASCII
  268.         aam
  269.         add     ax,'00'
  270.         xchg    al,ah
  271.         mov     word ptr dstr,ax
  272.  
  273.         mov     al,byte ptr es:[10h]    ; convert day to ASCII
  274.         aam
  275.         add     ax,'00'
  276.         xchg    al,ah
  277.         mov     word ptr dstr+3,ax
  278.  
  279.         mov     ax,word ptr es:[12h]    ; convert year to ASCII
  280.         sub     ax,1900
  281.         aam
  282.         add     ax,'00'
  283.         xchg    al,ah
  284.         mov     word ptr dstr+6,ax
  285.  
  286.         mov     si,offset DGROUP:dstr   ; insert date stamp string
  287.         call    stuff                   ; into keyboard data stream
  288.  
  289.         ret                             ; back to caller
  290.  
  291. date    endp
  292.  
  293.  
  294. time    proc    near                    ; format and insert time stamp
  295.  
  296.         mov     es,gseg                 ; get selector for global
  297.                                         ; read-only information segment 
  298.  
  299.         mov     al,byte ptr es:[8]      ; convert hours to ASCII
  300.         aam
  301.         add     ax,'00'
  302.         xchg    al,ah
  303.         mov     word ptr tstr,ax
  304.  
  305.         mov     al,byte ptr es:[9]      ; convert minutes to ASCII
  306.         aam
  307.         add     ax,'00'
  308.         xchg    al,ah
  309.         mov     word ptr tstr+3,ax
  310.  
  311.         mov     si,offset DGROUP:tstr   ; insert time stamp string
  312.         call    stuff                   ; into keyboard data stream
  313.  
  314.         ret                             ; back to caller
  315.  
  316. time    endp
  317.  
  318.  
  319. stuff   proc    near                    ; insert string into keyboard
  320.                                         ; data stream.  Call with
  321.                                         ; SI = ASCIIZ string (null
  322.                                         ;      is discarded)
  323.                                         ; AL, SI destroyed.
  324.  
  325. stuff1: lodsb                           ; get next character
  326.         or      al,al                   ; is it null?
  327.         jnz     stuff2                  ; no, use it
  328.         ret                             ; yes, exit
  329.  
  330. stuff2: mov     packet+2,al             ; place ASCII code into packet
  331.  
  332.                                         ; now send this character
  333.                                         ; to the keyboard driver...
  334.         push    ds                      ; address of monitor output buffer
  335.         push    offset DGROUP:monout
  336.         push    ds                      ; address of keyboard data packet
  337.         push    offset DGROUP:packet    
  338.         push    pktlen                  ; length of data packet
  339.         call    DOSMONWRITE             ; transfer to OS/2
  340.         jmp     stuff1                  ; do another character  
  341.  
  342. stuff   endp
  343.  
  344.  
  345. signon  proc    near                    ; use pop-up window to 
  346.                                         ; display help message
  347.  
  348.         push    ds                      ; put up PopUp window
  349.         push    offset DGROUP:popflag   ; (wait until available)
  350.         push    0
  351.         call    VIOPOPUP
  352.  
  353.         mov     dx,offset DGROUP:msg2   ; message address
  354.         mov     cx,msg2_len             ; length
  355.         mov     ax,9                    ; Y coordinate
  356.         call    center                  ; display it
  357.  
  358.         mov     dx,offset DGROUP:msg3   ; message address
  359.         mov     cx,msg3_len             ; length
  360.         mov     ax,13                   ; Y coordinate
  361.         call    center                  ; display it
  362.  
  363.         mov     dx,offset DGROUP:msg4   ; message address
  364.         mov     cx,msg4_len             ; length
  365.         mov     ax,15                   ; Y coordinate
  366.         call    center                  ; display it
  367.  
  368.         mov     dx,offset DGROUP:msg5   ; message address
  369.         mov     cx,msg5_len             ; length
  370.         mov     ax,17                   ; Y coordinate
  371.         call    center                  ; display it
  372.  
  373.         push    0                       ; pause for 3 seconds   
  374.         push    3000                    ; (user must be quick reader!)
  375.         call    DOSSLEEP
  376.  
  377.         push    0                       ; take down PopUp window
  378.         call    VIOENDPOPUP
  379.  
  380.         ret                             ; back to caller
  381.  
  382. signon  endp
  383.  
  384.  
  385. signoff proc    near                    ; use pop-up window to
  386.                                         ; announce exit
  387.  
  388.         push    ds                      ; put up PopUp window
  389.         push    offset DGROUP:popflag   ; (wait until available)
  390.         push    0
  391.         call    VIOPOPUP
  392.  
  393.         mov     dx,offset DGROUP:msg6   ; message address
  394.         mov     cx,msg6_len             ; length
  395.         mov     ax,12                   ; Y coordinate
  396.         call    center                  ; display it
  397.  
  398.         push    0                       ; pause for 1 seconds   
  399.         push    1000                    ; (user must not blink 
  400.         call    DOSSLEEP                ;  at wrong time...)    
  401.  
  402.         push    0                       ; take down PopUp window
  403.         call    VIOENDPOPUP
  404.  
  405.         ret                             ; back to caller
  406.  
  407. signoff endp
  408.  
  409.  
  410. center  proc    near                    ; center a message on screen
  411.                                         ; call DX = msg offset,
  412.                                         ; CX = length, AX = Y coordinate
  413.  
  414.         push    ds                      ; address of message
  415.         push    dx
  416.         push    cx                      ; length of message
  417.         push    ax                      ; Y
  418.         sub     cx,80                   ; X=((80-length)/2)
  419.         neg     cx
  420.         shr     cx,1
  421.         push    cx
  422.         push    0                       ; VIO handle
  423.         call    VIOWRTCHARSTR           ; transfer to OS/2
  424.         ret                             ; back to caller
  425.  
  426. center  endp
  427.  
  428. _TEXT   ends
  429.  
  430.         end     main
  431.